/**
 * 
 */
package com.edocbase.desktop.search;

import java.io.IOException;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
import org.apache.lucene.search.highlight.TokenSources;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;

/**
 * @author X61
 * @param <E>
 * @param <E>
 * 
 */
public class DocumentPageList extends AbstractPageList implements IPageList {
	/**
	 * 
	 */
	private static final long serialVersionUID = -1767803043008467773L;
	private TopDocs topDocs = null;
	private int descSize = 400;

	private IndexSearcher searcher = null;
	private SearchEngine engine = null;
	private Query query = null;
	private QueryScorer scorer;
	private Highlighter highlighter;
	private Fragmenter fragmenter;
	private IDocumentStoreFetcher storeFetcher;
	DocumentPageList(SearchEngine searchEngine, TopDocs topDocs,
			IndexSearcher searcher) throws Exception {
		this(searchEngine, topDocs, 10, searcher);

	}

	DocumentPageList(SearchEngine searchEngine, TopDocs topDocs, int pageSize,
			IndexSearcher searcher) throws Exception {
		this.engine = searchEngine;
		this.searcher = searcher;
		this.topDocs = topDocs;
		this.pageSize = pageSize;
		this.totalSize = topDocs.totalHits;
		computePage();
	}

	void setQuery(Query query) {
		this.query = query;
	}

	public IDocumentStoreFetcher getStoreFetcher() {
		return storeFetcher;
	}

	public void setStoreFetcher(IDocumentStoreFetcher storeFetcher) {
		this.storeFetcher = storeFetcher;
	}

	protected DocumentPage fetchPage(int start, int end)
	throws Exception {
		DocumentPage docPage = new DocumentPage(pageSize);
		for (; start < end; start++) {
			int docId = topDocs.scoreDocs[start].doc;
			Document doc = searcher.doc(docId);
			DiaryDocument ddoc = new DiaryDocument(doc);
			ddoc = fetchDocument(ddoc,doc);
			String content = getHighlightContent(ddoc);
			ddoc.setContent(content);
			docPage.add(ddoc);
		}
		return docPage;
	}
	protected DiaryDocument fetchDocument(DiaryDocument ddoc,Document doc){
		if (storeFetcher != null){
			ddoc = storeFetcher.fetchDocument(ddoc,doc);
			return ddoc;
		}
		return ddoc;
	}
	public String getHighlightContent(DiaryDocument ddoc) {
		try {
			// if (highlighter == null) {
			scorer = new QueryScorer(query, ISearchEngine.CONTENT_FIELD);
			highlighter = new Highlighter(scorer);
			fragmenter = new SimpleSpanFragmenter(scorer);
			highlighter.setTextFragmenter(fragmenter);
			// }
			TokenStream stream = TokenSources.getAnyTokenStream(searcher
					.getIndexReader(), descSize, ISearchEngine.CONTENT_FIELD,
					ddoc.doc, engine.analyzer);

			String content = ddoc.doc.get(ISearchEngine.CONTENT_FIELD);
			content = Jsoup.clean(content, Whitelist.simpleText());
			String fragment = null;
//			try{
//				fragment = highlighter.getBestFragment(stream, content);
//			}catch(Exception e){
//				e.printStackTrace(System.err);
//			}
			if (fragment == null){
				int size = Math.min(content.length(), descSize);
				fragment = content.substring(0,size);
			}
			return fragment;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	@Override
	public String toString() {
		return "DocumentPageList [engine=" + engine + ", fragmenter="
				+ fragmenter + ", highlighter=" + highlighter + ", page="
				+ page + ", pageList=" + pageList + ", pageSize=" + pageSize
				+ ", query=" + query + ", scorer=" + scorer + ", searcher="
				+ searcher + ", topDocs=" + topDocs + ", totalPage="
				+ totalPage + ", totalSize=" + totalSize + ", word=" + word
				+ "]";
	}

	@Override
	public void close() {
		super.close();
		try {
			searcher.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		topDocs = null;
	}

}
